import java.io.*;

public class BitInStream {
	private InputStream in;	
	private int nextByte;  // between 00000000 and 11111111 or -1 if EOF	
	private int numBitsRemaining;  // between 0 and 7	
	private boolean isEOF;
	
	
	
	public BitInStream(InputStream in) {
		if (in == null)
			throw new NullPointerException("input stream is null");
		this.in = in;
		numBitsRemaining = 0;
		isEOF = false;
	}
	
	
	
	// Reads a bit from the stream. Returns 0 or 1 if a bit is available, or -1 if the end of stream is reached. The end of stream always occurs on a byte boundary.
	public int read() throws IOException {
		if (isEOF) //end of file
			return -1;
		if (numBitsRemaining == 0) {
			nextByte = in.read();
			if (nextByte == -1) {//end of file
				isEOF = true;
				return -1;
			}
			numBitsRemaining = 8;//restart with new byte
		}
		numBitsRemaining--;
		return (nextByte >>> numBitsRemaining) & 1;//shifts all bits to the right by the number of bits remaining to check and does &1 to get the last bit
	}
	
	
	// Reads a bit from the stream. Returns 0 or 1 if a bit is available, or throws an EOFException if the end of stream is reached.
	public int readNoEof() throws IOException {
		int result = read();
		if (result != -1)
			return result;
		else
			throw new EOFException("End of file");
	}
	
	
	// Closes this stream and the underlying InputStream.
	public void close() throws IOException {
		in.close();
	}
	
}
